﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Adams.Admin.Business.Security
{
    public class Login
    {
        private const int _AllowedLoginAttempts = 5;
        private const int _LockoutIncrementInMinutes = 5;

        public static DataTransfer.Security.Login.LoginOutput TryLogin(DataTransfer.Security.Login.LoginInput input)
        {
            var ret = new DataTransfer.Security.Login.LoginOutput(); // Create Output Class

            # region Validate Input
            bool isInputValid = true;

            //// Validate Email
            //if (Shared.Validation.Empty(input.Email, 1, ref ret.EmailValidationCode, ref isInputValid))
            //{
            //    if (Shared.Validation.Size(input.Email, 50, 2, ref ret.EmailValidationCode, ref isInputValid))
            //    {
            //        if (Shared.Validation.RegEx(input.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$", 3, ref ret.EmailValidationCode, ref isInputValid))
            //        {

            //        }
            //    }
            //}

            //// Validate Password
            //if (Shared.Validation.Empty(input.Password, 1, ref ret.PasswordValidationCode, ref isInputValid))
            //{
            //    if (Shared.Validation.Size(input.Password, 50, 2, ref ret.PasswordValidationCode, ref isInputValid))
            //    {

            //    }
            //}

            #endregion

            if (isInputValid)
            {
                var data = DataAccess.Security.Login.GetUserInfo(input.Email); // Get User Information

                if (data.Exists)
                {
                    // User does exist
                    if (data.IsActive)
                    {
                        // User is active
                        // Check if account is locked
                        if (Adams.Shared.SecurityHelper.IsLocked(data.FailedLoginAttempts, data.LastLoginAttempt, _AllowedLoginAttempts, _LockoutIncrementInMinutes))
                        {
                            // User is locked out
                            ret.IsLocked = true;
                            ret.LockWaitMinutes = Adams.Shared.SecurityHelper.GetLockWaitMinutes(data.FailedLoginAttempts, data.LastLoginAttempt, _AllowedLoginAttempts, _LockoutIncrementInMinutes);
                        }
                        else
                        {
                            // Check if password is valid
                            string hashedPassword = Adams.Shared.Encryption.HashPassword(input.Password, data.PasswordSalt);
                            bool isPasswordValid = Shared.Str.IsEqual(hashedPassword, data.PasswordHash);

                            if (isPasswordValid)
                            {
                                // Login Successful
                                DataAccess.Security.Login.ClearLockout(data.UserID); // Clear lockout info
                                ret.UserID = data.UserID;
                                ret.IsValid = true;
                            }
                            else
                            {
                                // Invalid password
                                DataAccess.Security.Login.UpdateLockout(data.UserID); // Update lockout info
                                data.FailedLoginAttempts++;

                                if (data.FailedLoginAttempts >= _AllowedLoginAttempts)
                                {
                                    ret.IsLocked = true;
                                    ret.LockWaitMinutes = Adams.Shared.SecurityHelper.GetLockWaitMinutes(data.FailedLoginAttempts, DateTime.UtcNow, _AllowedLoginAttempts, _LockoutIncrementInMinutes);
                                }
                                else
                                {
                                    ret.IsInvalidPassword = true;
                                }

                                ret.AttemptsLeft = _AllowedLoginAttempts - data.FailedLoginAttempts;
                            }
                        }
                    }
                    else
                    {
                        ret.IsNotActive = true;
                    }
                }
            }
            else
            {
                // User input invalid
                ret.IsInvalidInput = true;
            }

            return ret;
        }
    }
}
